/* Copyright (c) [2020] juruoyun developer team
     Juruoyun basic lib is licensed under the Mulan PSL v1.
     You can use this software according to the terms and conditions of the Mulan PSL v1.
     You may obtain a copy of Mulan PSL v1 at:
            http://license.coscl.org.cn/MulanPSL
     THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
     IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
     PURPOSE.
     See the Mulan PSL v1 for more details.*/
#include "jbl_ht.h"
#if JBL_HT_ENABLE==1
/*******************************************************************************************/
/*                            依赖 jbl_gc jbl_malloc jbl_var jbl_ying                      */
/*                                 jbl_exception jbl_string                                */
/*******************************************************************************************/
#include "jbl_gc.h"
#include "jbl_malloc.h"
#include "jbl_var.h"
#include "jbl_ying.h"
#include "jbl_string.h"
#include "jbl_exception.h"
/*******************************************************************************************/
/*                            联动 jbl_json jbl_stream jbl_ll                              */
/*******************************************************************************************/
#include "jbl_json.h"
#include "jbl_stream.h"
#include "jbl_ll.h"
/*******************************************************************************************/
/*                            以下函实现哈希表数据节点操作                               */
/*******************************************************************************************/
static void __data_init(jbl_ht_data *this);
static void __data_free(jbl_ht_data *this);
static JBL_INLINE void __data_init(jbl_ht_data *this)
{
    this->k=NULL;
    this->v=NULL;
    this->h=0;
    this->nxt=((jbl_ht_size_type)-1);
}
static JBL_INLINE void __data_free(jbl_ht_data *this)
{
    this->k=jbl_string_free(this->k);
    this->v=jbl_var_free(this->v);
    this->h=0;
    this->nxt=((jbl_ht_size_type)-1);
}
#if JBL_HT_SYS_ENABLE==1
static void __data_free2(jbl_ht_data *this);
static void* __sys_vc(void *this);
static void* __sys_vf(void *this);
#define is_sys(x) (jbl_gc_is_user1(x))        //获取sys标记
static JBL_INLINE void __data_free2(jbl_ht_data *this)
{
    this->k=jbl_string_free(this->k);
    this->h=0;
    this->nxt=((jbl_ht_size_type)-1);
}
static JBL_INLINE void* __sys_vf(void *this){return this=NULL;}
static JBL_INLINE void* __sys_vc(void *this){return this;}
#endif
/*******************************************************************************************/
/*                            全局变量定义                                                */
/*******************************************************************************************/
#if JBL_LL_ENABLE==1 && JBL_HT_SYS_ENABLE ==1 && JBL_HT_STRUCTER_ENABLE ==1
static jbl_ht *__structer_func=NULL;
#endif
/*******************************************************************************************/
/*                            以下函数完成字符串组件启动和停止                           */
/*******************************************************************************************/
void jbl_ht_start()
{
#if JBL_LL_ENABLE==1 && JBL_HT_SYS_ENABLE ==1 && JBL_HT_STRUCTER_ENABLE ==1
    __structer_func=jbl_ht_new();
    jbl_ht_set_sys(__structer_func);
#endif
}
void jbl_ht_stop()
{
#if JBL_LL_ENABLE==1 && JBL_HT_SYS_ENABLE ==1 && JBL_HT_STRUCTER_ENABLE ==1
    __structer_func=jbl_ht_free(__structer_func);
#endif
}
/*******************************************************************************************/
/*                            以下函实现哈希表基本操作                                   */
/*******************************************************************************************/
#define htvh(x) for(jbl_ht_size_type i=0;i<(x)->size;jbl_stream_push_char(jbl_stream_stdout,' '),jbl_stream_push_int(jbl_stream_stdout,(jbl_ht_size_type_signed)((jbl_ht_size_type*)(x)->data)[-i-1]),++i);jbl_stream_push_char(jbl_stream_stdout,'\n')        //查看hash值
#define gh2(x,y) ((jbl_ht_size_type_signed)(((jbl_ht_size_type)(y))|(-(jbl_ht_size_type)(x)->size)))
jbl_var_operators_new(jbl_ht_operators,jbl_ht_free,jbl_ht_copy,jbl_ht_space_ship,jbl_ht_json_encode,jbl_ht_view_put,jbl_ht_json_put);
jbl_ht * jbl_ht_new()
{
    jbl_ht * this=jbl_malloc(sizeof(jbl_ht));
    jbl_gc_init(this);
    jbl_gc_plus(this);
    jbl_pthread_lock_init(this);
    jbl_var_set_operators(this,&jbl_ht_operators);
    this->size=this->len=this->nxt=0;
    this->data=NULL;
    return this;
}
jbl_ht* jbl_ht_free(jbl_ht *this)
{
    if(!this)return NULL;
    jbl_pthread_lock_wrlock(this);
    jbl_gc_minus(this);
    if(!jbl_gc_refcnt(this))
    {
        if(jbl_gc_is_ref(this))
            jbl_ht_free((jbl_ht*)(((jbl_reference*)this)->ptr));
        else
            if(this->size!=0)
            {
#if JBL_HT_SYS_ENABLE==1
                if(is_sys(this))
                    for(register jbl_ht_size_type i=0;i<this->size;__data_free2(&this->data[i]),++i);
                else
#endif
                    for(register jbl_ht_size_type i=0;i<this->size;__data_free(&this->data[i]),++i);
                jbl_free((char*)this->data-sizeof(jbl_ht_size_type)*this->size);
            }
        jbl_pthread_lock_free(this);
        jbl_free(this);
    }
        else{jbl_pthread_lock_unwrlock(this);}
    return NULL;
}
JBL_INLINE jbl_ht *jbl_ht_copy(jbl_ht *that)
{
    if(!that)return NULL;
    jbl_pthread_lock_wrlock(that);
    jbl_gc_plus(that);
    jbl_pthread_lock_unwrlock(that);    
    return that;
}
jbl_ht * jbl_ht_extend_to(jbl_ht *this,jbl_ht_size_type size,jbl_uint8 add,jbl_ht **pthi)
{
//size不够扩
//分离
    if(!this)this=jbl_ht_new();
    jbl_reference *ref=NULL;jbl_ht *thi=jbl_refer_pull_keep_father_wrlock(this,&ref);    
#if JBL_HT_SYS_ENABLE==1
    void*(*copy)(void*)=(is_sys(this)?__sys_vc:jbl_var_copy);
#else 
    #define copy jbl_var_copy
#endif
    //size计算
    jbl_ht_size_type size_need=size+(thi->len)*(add&1);                //装下当前数据需要的size
    size+=(thi->nxt)*(add&1);                                        //加上末尾的
    jbl_max_update(size,JBL_HT_MIN_SIZE);                            //最小值
    size=1ULL<<(jbl_highbit(size-1)+1);                                //2的倍数
    jbl_ht *tmp=NULL;
    if(jbl_gc_refcnt(thi)==1)                                        //不是多个并用
    {
        if(size<=thi->size)                                            //空间足够
            goto exit;
        else if((size_need<<1)<thi->size)                            //有一半的限制节点，可以rehash
        {
            thi=jbl_ht_rehash(thi);
            goto exit;
        }
        //需要重新搞，直接进入下面
    }
    //多个分离
    tmp=jbl_ht_new();
    jbl_pthread_lock_wrlock(tmp);
#if JBL_HT_SYS_ENABLE==1
    if(is_sys(thi))
        jbl_ht_set_sys(tmp);
#endif    
    //申请新空间，初始化
    tmp->size=size;
    tmp->data=(jbl_ht_data*)(((char*)jbl_malloc(tmp->size*(sizeof(jbl_ht_data)+sizeof(jbl_ht_size_type))))+sizeof(jbl_ht_size_type)*tmp->size);
    for(register jbl_ht_size_type i=0;i<tmp->size;__data_init(&tmp->data[i]),((jbl_ht_size_type*)tmp->data)[-i-1]=-1ULL,++i);
    if(thi->data)
    {
        for(register jbl_ht_size_type j=0;j<thi->nxt;++j)    //遍历这个结构
            if(thi->data[j].v!=NULL)                        //使用
            {
                jbl_int64 h2=gh2(tmp,tmp->data[tmp->nxt].h=thi->data[j].h);
                tmp->data[tmp->nxt].k=jbl_string_copy(thi->data[j].k);
                tmp->data[tmp->nxt].v=copy(thi->data[j].v);
                tmp->data[tmp->nxt].nxt=((jbl_ht_size_type*)tmp->data)[h2];
                ((jbl_ht_size_type*)tmp->data)[h2]=tmp->nxt;
                ++tmp->nxt;
                ++tmp->len;
            }
    }
    jbl_pthread_lock_unwrlock(thi);
    jbl_ht_free(thi);
    thi=tmp;
exit:;    
    if(ref)        ref->ptr=thi;
    else        this=thi;
    if(pthi)    *pthi=thi;
    else        {jbl_refer_pull_unwrlock(this);}
    return this;
}
jbl_ht * jbl_ht_rehash(jbl_ht *this)
{
    if(!this)return NULL;
    jbl_ht * thi=NULL;this=jbl_ht_extend_to(this,0,1,&thi);
    if(thi->data==NULL)return this;
    register jbl_ht_size_type i=0,j=0;
#if JBL_HT_SYS_ENABLE==1
    void*(*copy)(void*)=(is_sys(this)?__sys_vc:jbl_var_copy);
    void (*dfree)(jbl_ht_data*)=(is_sys(this)?__data_free2:__data_free);
#else 
    #define copy jbl_var_copy
    #define dfree __data_free
#endif
    for(;j<thi->nxt&&thi->data[j].v!=NULL;++j);    
    for(i=j+1;i<thi->nxt;++i)
        if(thi->data[i].v!=NULL&&j<i)
        {
            jbl_int64 h2=gh2(thi,thi->data[j].h=thi->data[i].h);        
            thi->data[j].k=jbl_string_copy(thi->data[i].k);
            thi->data[j].v=copy(thi->data[i].v);
            thi->data[j].nxt=(((jbl_ht_size_type*)thi->data)[h2]>=i)?(thi->data[i].nxt):(((jbl_ht_size_type*)thi->data)[h2]);
            ((jbl_ht_size_type*)thi->data)[h2]=j;        
            ++j;
            dfree(&thi->data[i]);
        }
    thi->nxt=j;
#if JBL_HT_SYS_ENABLE == 0
    #undef copy
    #undef dfree
#endif
    jbl_refer_pull_unwrlock(this);
    return this;
}
/*******************************************************************************************/
/*                            以下函实现哈希表插入操作                                   */
/*******************************************************************************************/
jbl_ht * __jbl_ht_insert(jbl_ht *this,jbl_string_hash_type h,jbl_string *k,void *v)
{
    jbl_ht * thi=NULL;this=jbl_ht_extend_to(this,1,1,&thi);
    jbl_ht_size_type_signed h2=gh2(thi,h);
    for(register jbl_ht_size_type i=((jbl_ht_size_type*)thi->data)[h2];i<thi->nxt;i=thi->data[i].nxt)
        if(h==thi->data[i].h&&jbl_string_if_equal(thi->data[i].k,k))
        {
#if JBL_HT_SYS_ENABLE==1
            if(is_sys(thi))
                thi->data[thi->nxt].v=v;
            else
#endif
            jbl_var_free(thi->data[i].v),thi->data[i].v=v?jbl_var_copy(v):jbl_Vnull_new();
            return thi;
        }
    thi->data[thi->nxt].h=h;
    thi->data[thi->nxt].k=jbl_string_copy(jbl_refer_pull(k));
#if JBL_HT_SYS_ENABLE==1
    if(is_sys(thi))
        thi->data[thi->nxt].v=v;
    else
#endif
        thi->data[thi->nxt].v=v?jbl_var_copy(v):jbl_Vnull_new();
    thi->data[thi->nxt].nxt=((jbl_ht_size_type*)thi->data)[h2];
    ((jbl_ht_size_type*)thi->data)[h2]=thi->nxt;
    ++thi->len;
    ++thi->nxt;
    jbl_refer_pull_unwrlock(this);
    return this;
}
jbl_ht * jbl_ht_insert_force(jbl_ht *this,jbl_string_hash_type h,jbl_string *k,void *v)
{
    jbl_ht * thi=NULL;this=jbl_ht_extend_to(this,1,1,&thi);
    jbl_ht_size_type_signed h2=gh2(thi,h);
    thi->data[thi->nxt].h=h;
    thi->data[thi->nxt].k=jbl_string_copy(jbl_refer_pull(k));
#if JBL_HT_SYS_ENABLE==1
    if(is_sys(thi))
        thi->data[thi->nxt].v=v;
    else
#endif
    thi->data[thi->nxt].v=v?jbl_var_copy(v):jbl_Vnull_new();
    thi->data[thi->nxt].nxt=((jbl_ht_size_type*)thi->data)[h2];
    ((jbl_ht_size_type*)thi->data)[h2]=thi->nxt;
    ++thi->len;
    ++thi->nxt;
    jbl_refer_pull_unwrlock(this);
    return this;
}
JBL_INLINE jbl_ht  * jbl_ht_insert        (jbl_ht *this,jbl_string *k,void *v)        {return __jbl_ht_insert(this,jbl_string_hash(k),k,v);}
JBL_INLINE jbl_ht  * jbl_ht_insert_chars(jbl_ht *this,unsigned char *kk,void *v)    {jbl_string * k=jbl_string_add_chars(NULL,kk);this=jbl_ht_insert(this,k,v);jbl_string_free(k);return this;}
JBL_INLINE jbl_ht  * jbl_ht_insert_int    (jbl_ht *this,jbl_string_hash_type h,void *v)                {return __jbl_ht_insert(this,h,NULL,v);}
/*******************************************************************************************/
/*                            以下函实现哈希表删除操作                                   */
/*******************************************************************************************/
jbl_ht * __jbl_ht_unset(jbl_ht *this,jbl_string_hash_type h,jbl_string *k)
{
    jbl_ht * thi=NULL;this=jbl_ht_extend_to(this,0,1,&thi);
    if(thi->size!=0)
    {
        jbl_ht_size_type_signed h2=gh2(thi,h);
        for(register jbl_ht_size_type i=((jbl_ht_size_type*)thi->data)[h2],j=-1ULL;i<thi->nxt;j=i,i=thi->data[i].nxt)
            if(h==thi->data[i].h&&jbl_string_if_equal(thi->data[i].k,k))
            {
                if(j==-1ULL)
                    (((jbl_ht_size_type*)thi->data)[h2])=thi->data[i].nxt;
                else
                    thi->data[j].nxt=thi->data[i].nxt;
#if JBL_HT_SYS_ENABLE==1
                if(is_sys(thi))
                    __data_free2(&thi->data[i]);
                else
#endif
                __data_free(&thi->data[i]);
                --thi->len;
                break;
            }
    }
    jbl_refer_pull_unwrlock(this);
    return this;
}
JBL_INLINE jbl_ht  * jbl_ht_unset        (jbl_ht *this,jbl_string *k)                {return __jbl_ht_unset(this,jbl_string_hash(k),k);}
JBL_INLINE jbl_ht  * jbl_ht_unset_chars    (jbl_ht *this,unsigned char *kk)            {jbl_string * k=jbl_string_add_chars(NULL,kk);this=jbl_ht_unset(this,k);jbl_string_free(k);return this;}
JBL_INLINE jbl_ht  * jbl_ht_unset_int    (jbl_ht *this,jbl_string_hash_type h)       {return __jbl_ht_unset(this,h,NULL);}
/*******************************************************************************************/
/*                            以下函实现哈希表获取操作                                   */
/*******************************************************************************************/
JBL_INLINE void * jbl_htv(jbl_ht_data *node){return node->v;}
JBL_INLINE jbl_string * jbl_htk(jbl_ht_data *node){return node->k;}
JBL_INLINE jbl_string_hash_type jbl_hth(jbl_ht_data *node){return node->h;}
jbl_ht_data * jbl_ht_get_ht_data(jbl_ht *this,jbl_string *k)
{
    jbl_ht *thi=jbl_refer_pull_rdlock(this);        
    jbl_ht_data * ans=NULL;
    if(thi->size!=0&&k)
    {
        jbl_string_hash_type h=jbl_string_hash(k);
        jbl_ht_size_type_signed    h2=gh2(thi,h);
        for(register jbl_ht_size_type i=((jbl_ht_size_type*)thi->data)[h2];i<thi->nxt;i=thi->data[i].nxt)
            if(h==thi->data[i].h&&jbl_string_if_equal(thi->data[i].k,k))
            {
                ans=&thi->data[i];
                break;
            }
    }
    jbl_refer_pull_unrdlock(this);
    return ans;
}
jbl_ht_data * jbl_ht_get_ht_data_chars(jbl_ht *this,const jbl_uint8 *chars)
{
    jbl_ht *thi=jbl_refer_pull_rdlock(this);        
    jbl_ht_data * ans=NULL;
    jbl_string_hash_type h=jbl_strhash(chars,0);
    if(thi->size!=0&&chars)
    {
        jbl_ht_size_type_signed    h2=gh2(thi,h);
        for(register jbl_ht_size_type i=((jbl_ht_size_type*)thi->data)[h2];i<thi->nxt;i=thi->data[i].nxt)
            if(h==thi->data[i].h&&!jbl_string_space_ship_chars(thi->data[i].k,(const char *)chars))
            {
                ans=&thi->data[i];
                break;
            }
    }
    jbl_refer_pull_unrdlock(this);
    return ans;
}
jbl_ht_data * jbl_ht_get_ht_data_int(jbl_ht *this,jbl_string_hash_type h)
{
    jbl_ht *thi=jbl_refer_pull_rdlock(this);        
    jbl_ht_data * ans=NULL;
    if(thi->size!=0)
    {
        jbl_ht_size_type_signed    h2=gh2(thi,h);
        for(register jbl_ht_size_type i=((jbl_ht_size_type*)thi->data)[h2];i<thi->nxt;i=thi->data[i].nxt)
            if(h==thi->data[i].h&&!thi->data[i].k)
            {
                ans=&thi->data[i];
                break;
            }
    }
    jbl_refer_pull_unrdlock(this);
    return ans;
}
JBL_INLINE void * jbl_ht_get(jbl_ht *this,jbl_string *k)
{
    jbl_refer_pull_rdlock(this);
    jbl_ht_data *data=jbl_ht_get_ht_data(this,k);
    void * ans=NULL;
    if(data)
    {
#if JBL_HT_SYS_ENABLE==1
        if(jbl_ht_is_sys(this))
            ans=data->v;
        else
#endif
        ans=jbl_var_copy(data->v);
    }
    jbl_refer_pull_unrdlock(this);    
    return ans;
}
JBL_INLINE void * jbl_ht_get_chars(jbl_ht *this,unsigned char *kk)
{
    jbl_refer_pull_rdlock(this);
    jbl_ht_data *data=jbl_ht_get_ht_data_chars(this,kk);
    void * ans=NULL;
    if(data)
    {
#if JBL_HT_SYS_ENABLE==1
        if(jbl_ht_is_sys(this))
            ans=data->v;
        else
#endif
        ans=jbl_var_copy(data->v);
    }
    jbl_refer_pull_unrdlock(this);    
    return ans;
}
JBL_INLINE void * jbl_ht_get_int(jbl_ht *this,jbl_string_hash_type h)
{
    jbl_refer_pull_rdlock(this);
    jbl_ht_data *data=jbl_ht_get_ht_data_int(this,h);
    void * ans=NULL;
    if(data)
    {
#if JBL_HT_SYS_ENABLE==1
        if(jbl_ht_is_sys(this))
            ans=data->v;
        else
#endif
        ans=jbl_var_copy(data->v);
    }
    jbl_refer_pull_unrdlock(this);    
    return ans;
}
JBL_INLINE jbl_ht_size_type jbl_ht_get_length(jbl_ht *this)
{
    jbl_ht_size_type ans=0;
    jbl_ht * thi=jbl_refer_pull_rdlock(this);
    if(thi)ans=thi->len;
    jbl_refer_pull_unrdlock(this);
    return ans;
}
#if JBL_LL_ENABLE==1
jbl_ll * jbl_ht_get_keys(jbl_ht *this,jbl_ll *ll)
{
    jbl_ht *thi=jbl_refer_pull_rdlock(this);
    jbl_ht_foreach(thi,i)
        ll=jbl_ll_add(ll,i->k);
    jbl_refer_pull_unrdlock(this);
    return ll;
}
jbl_string * jbl_ht_get_feature_string(jbl_ht *this)
{
    jbl_string *s1=NULL;
    jbl_ll * ll=jbl_ht_get_keys(this,NULL);
    ll=jbl_ll_sort(ll,NULL);
    jbl_ll_foreach(ll,i)
        if(jbl_string_find_char(jbl_llv(i),'\1')==-1ULL)
        {
            s1=jbl_string_add_string(s1,jbl_llv(i));
            s1=jbl_string_add_char(s1,'\1');
        }
    ll=jbl_ll_free(ll);
    return s1;
}
#endif
/*******************************************************************************************/
/*                            以下函实现哈希表转结构体操作                               */
/*******************************************************************************************/
#if JBL_LL_ENABLE==1 && JBL_HT_SYS_ENABLE ==1 && JBL_HT_STRUCTER_ENABLE ==1
void jbl_ht_structer_set(unsigned char * feature_string,void*(*set)(jbl_ht *))
{
    jbl_refer_pull_wrlock(__structer_func);
    jbl_string *str=jbl_string_add_const(NULL,feature_string);
    jbl_ht_data *data=jbl_ht_get_ht_data(__structer_func,str);
    if(!data)
        __structer_func=jbl_ht_insert_force(__structer_func,jbl_string_hash(str),str,set);
    str=jbl_string_free(str);
    jbl_refer_pull_unwrlock(__structer_func);
}
void * jbl_ht_structer(jbl_ht* this)
{
    jbl_ht *thi=jbl_refer_pull_rdlock(this);
    jbl_string* str=jbl_ht_get_feature_string(thi);
    jbl_ht_data *data=jbl_ht_get_ht_data(__structer_func,str);
    void *ans=NULL;
    if(data&&data->v)
    {
        void*(*set)(jbl_ht *)=data->v;
        ans=set(thi);
    }
    else
        ans=jbl_ht_copy(thi);
    str=jbl_string_free(str);
    jbl_refer_pull_unrdlock(this);
    return ans;
}
#endif
/*******************************************************************************************/
/*                            以下函实现哈希表比较操作                                   */
/*******************************************************************************************/
char jbl_ht_space_ship(jbl_ht *this,jbl_ht *that)
{
    char ans=0;
    jbl_ht *thi=jbl_refer_pull_rdlock(this);
    jbl_ht *tha=jbl_refer_pull_rdlock(that);    
    if(thi==tha){ans=0;goto exit;}if(!thi){ans=-1;goto exit;}if(!tha){ans=1;goto exit;}
    if(thi->len!=tha->len)
        {ans=(thi->len<tha->len)?-1:1;goto exit;}
#if JBL_HT_SYS_ENABLE==1
    if(is_sys(thi)){ans=-1;goto exit;}
    if(is_sys(tha)){ans=1;goto exit;}
#endif
    void *v2;
    jbl_ht_foreach(thi,i)
    {
        v2=jbl_ht_get(tha,i->k);
        ans=jbl_var_space_ship(i->v,v2);
        v2=jbl_var_free(v2);
        if(!ans) goto exit;
    }
exit:;
    jbl_refer_pull_unrdlock(this);
    jbl_refer_pull_unrdlock(that);
    return ans;
}
/*******************************************************************************************/
/*                            以下函实现哈希表合并操作                                   */
/*******************************************************************************************/
jbl_ht * jbl_ht_merge(jbl_ht *this,jbl_ht *that)
{
    if(!that)return this;
    jbl_ht *tha=jbl_refer_pull_rdlock(that);    
#if JBL_HT_SYS_ENABLE==1
    if(jbl_ht_is_sys(this)==jbl_ht_is_sys(tha))
#endif
        jbl_ht_foreach(tha,i)
            this=__jbl_ht_insert(this,i->h,i->k,i->v);
    return this;
}
jbl_ht * jbl_ht_merge_int(jbl_ht *this)
{
    jbl_ht * thi=NULL;this=jbl_ht_extend_to(this,0,1,&thi);
    if(thi->data)
    {
#if JBL_HT_SYS_ENABLE==1
        void*(*copy)(void*)=(is_sys(this)?__sys_vc:jbl_var_copy);
        void*(*fre)(void*)=(is_sys(this)?__sys_vf:jbl_var_free);
#else 
    #define copy jbl_var_copy
    #define fre jbl_var_free
#endif
        for(register jbl_ht_size_type i=0,j;i<thi->nxt;++i)
            if((!thi->data[i].k)&&thi->data[i].v)
            {
                jbl_string *s=jbl_string_add_uint(NULL,thi->data[i].h);
                char flag=0;
                jbl_string_hash_type h=jbl_string_hash(s);
                jbl_ht_size_type_signed    h2=gh2(thi,h);
                for(j=((jbl_ht_size_type*)thi->data)[h2];j<thi->nxt;j=thi->data[j].nxt)
                    if(h==thi->data[j].h&&jbl_string_if_equal(thi->data[j].k,s))
                    {flag=1;break;}
                if(flag)
                    {if(i>j)fre(thi->data[j].v),thi->data[j].v=copy(thi->data[i].v);}
                else
                {
                    this=jbl_ht_extend(this,1);    
                    thi=jbl_refer_pull(this);
                    h2=gh2(thi,h);
                    thi->data[thi->nxt].h=h;
                    thi->data[thi->nxt].k=jbl_string_copy(s);
                    thi->data[thi->nxt].v=copy(thi->data[i].v);
                    thi->data[thi->nxt].nxt=((jbl_ht_size_type*)thi->data)[h2];
                    ((jbl_ht_size_type*)thi->data)[h2]=thi->nxt;
                    ++thi->len;
                    ++thi->nxt;
                }
                __data_free(&thi->data[i]);
                jbl_string_free(s);
                
            }
#if JBL_HT_SYS_ENABLE == 0
    #undef copy
    #undef fre
#endif
    }
    jbl_refer_pull_unwrlock(this);
    return this;
}
#if JBL_LL_ENABLE==1
jbl_ht *jbl_ht_merge_ll(jbl_ht *this,jbl_ll *that)
{
#if JBL_HT_SYS_ENABLE==1
    if(this&&jbl_ht_is_sys(this))return NULL;
#endif
    jbl_ll * tha=jbl_refer_pull_rdlock(that);
    jbl_ll_size_type j=0;
    jbl_ll_foreach(tha,i)
        this=jbl_ht_insert_int(this,j++,i->v);
    jbl_refer_pull_unrdlock(that);
    return this;
}
#endif
/*******************************************************************************************/
/*                            以下函实现哈希表JSON操作                                   */
/*******************************************************************************************/
#if JBL_JSON_ENABLE==1
jbl_string* jbl_ht_json_encode(jbl_ht* this,jbl_string *out,jbl_uint8 format,jbl_uint32 tabs)
{
    jbl_ht *thi=jbl_refer_pull_rdlock(this);
#if JBL_HT_SYS_ENABLE==1
    if(thi&&is_sys(thi))this=NULL;
#endif
    out=jbl_string_json_put_format(thi,out,format,tabs);
    if(thi)
    {
        out=jbl_string_add_char(out,'{');
        if((format&1)||(format&4))out=jbl_string_add_char(out,'\n');
        ++tabs;
        jbl_uint8 format2=(jbl_uint8)((format&4)|((format&1)<<2));
        jbl_ht_data * tail=this->data+this->nxt-1;
        jbl_ht_foreach(this,i)
        {
            if(i->k==NULL)continue;
            if((format&1)||(format&4))for(jbl_uint32 j=0;j<tabs;out=jbl_string_add_chars(out,UC JBL_JSON_TAB),++j);
            if(i->k==NULL)
                out=jbl_string_add_uint(out,i->h);
            else
                out=jbl_string_json_encode(i->k,out,0,0);
            out=jbl_string_add_char(out,':');
            out=jbl_var_json_encode(i->v,out,(jbl_uint8)(format2|((i!=tail)<<1)),tabs);
        }    
        --tabs;if((format&1)||(format&4))for(jbl_uint32 j=0;j<tabs;out=jbl_string_add_chars(out,UC JBL_JSON_TAB),++j);//格式化的\t
        out=jbl_string_add_char(out,'}');
        if(format&2){out=jbl_string_add_char(out,',');}if((format&1)||(format&4)){out=jbl_string_add_char(out,'\n');}
        
    }
    jbl_refer_pull_unwrlock(out);
    jbl_refer_pull_unrdlock(this);
    return out;
}
#if JBL_STREAM_ENABLE==1
void jbl_ht_json_put(jbl_ht* this,jbl_stream *out,jbl_uint8 format,jbl_uint32 tabs)
{
    jbl_ht *thi=jbl_refer_pull_rdlock(this);
#if JBL_HT_SYS_ENABLE==1
    if(thi&&is_sys(thi))this=NULL;
#endif
    if(jbl_stream_json_put_format(thi,out,format,tabs))
    {
        jbl_stream_push_char(out,'{');
        if((format&1)||(format&4))jbl_stream_push_char(out,'\n');
        ++tabs;
        jbl_uint8 format2=(jbl_uint8)((format&4)|((format&1)<<2));
        jbl_ht_data * tail=this->data+this->nxt-1;
        jbl_ht_foreach(this,i)
        {
            if(i->k==NULL)continue;
            if((format&1)||(format&4))for(jbl_uint32 j=0;j<tabs;jbl_stream_push_chars(out,UC JBL_JSON_TAB),++j);//格式化的\t
            if(i->k==NULL)
                jbl_stream_push_uint(out,i->h);
            else
                jbl_string_json_put(i->k,out,0,0);
            jbl_stream_push_char(out,':');
            jbl_var_json_put(i->v,out,(jbl_uint8)(format2|((i!=tail)<<1)),tabs);
        }    
        --tabs;if((format&1)||(format&4))for(jbl_uint32 j=0;j<tabs;jbl_stream_push_chars(out,UC JBL_JSON_TAB),++j);//格式化的\t
        jbl_stream_push_char(out,'}');
        if(format&2){jbl_stream_push_char(out,',');}if((format&1)||(format&4)){jbl_stream_push_char(out,'\n');}
    }
    jbl_refer_pull_unwrlock(out);
    jbl_refer_pull_unrdlock(this);
}
#endif
#endif
#if JBL_STREAM_ENABLE==1
/*******************************************************************************************/
/*                            以下函实现哈希表浏览操作                                   */
/*******************************************************************************************/
jbl_ht* jbl_ht_view_put(jbl_ht* this,jbl_stream *out,jbl_uint8 format,jbl_uint32 tabs,jbl_uint32 line,unsigned char * varname,unsigned char * func,unsigned char * file)
{
    jbl_ht *thi=jbl_refer_pull_rdlock(this);
    if(jbl_stream_view_put_format(thi,out,format,tabs,UC"jbl_ht",line,varname,func,file))
    {
        jbl_stream_push_chars(out,UC " len:");
        jbl_stream_push_uint(out,thi->len);
        jbl_stream_push_chars(out,UC " nxt:");
        jbl_stream_push_uint(out,thi->nxt);
        jbl_stream_push_chars(out,UC " size:");
        jbl_stream_push_uint(out,thi->size);
        jbl_stream_push_char(out,'\n');
        ++tabs;
        jbl_ht_foreach(thi,i)
        {
            for(jbl_uint32 j=0;j<tabs;jbl_stream_push_chars(out,UC JBL_VIEW_TAB),++j);//格式化的\t
            if(i->k==NULL)
                jbl_stream_push_uint(out,i->h);
            else
                jbl_stream_push_char(out,'"'),jbl_stream_push_string(out,i->k),jbl_stream_push_char(out,'"');
            jbl_stream_push_char(out,':');
#if JBL_HT_SYS_ENABLE==1
            if(is_sys(thi))jbl_stream_push_uint(out,i->u),jbl_stream_push_char(out,'\n');
            else
#endif
            jbl_var_view_put(i->v,out,0,tabs,0,NULL,NULL,NULL);
        }
    }
    else
        jbl_stream_push_char(out,'\n');
    jbl_refer_pull_unwrlock(out);
    jbl_refer_pull_unrdlock(this);
    return this;
}
#endif

#endif